import time
from hashlib import md5

import xml.etree.ElementTree as ET
import requests


def basic_auth_picture(ip, user, password, pic_path):
    # Authorization: Basic
    uri = "/ISAPI/Streaming/channels/33/picture"
    resp = requests.get(f"http://{ip}{uri}", auth=(user, password))
    with open(pic_path, "wb") as f:
        f.write(resp.content)


def digest_auth_picture(ip, user, password, pic_path):
    # Authorization: Digest
    uri = "/ISAPI/Streaming/channels/33/picture"
    hearders = digest_auth(ip, user, password, uri)
    resp = requests.get(f"http://{ip}{uri}",
                        headers=hearders, auth=(user, password))
    with open(pic_path, "wb") as f:
        f.write(resp.content)


def digest_auth(ip, user, password, uri, method="GET"):
    # Authorization: digest
    resp = requests.get(f"http://{ip}{uri}")
    realm = resp.headers['WWW-Authenticate'].split('realm="')[1].split('"')[0]
    Basic_realm = resp.headers['WWW-Authenticate'].split('Basic realm="')[
        1].split('"')[0]
    nonce = resp.headers['WWW-Authenticate'].split('nonce="')[1].split('"')[0]
    qop = resp.headers['WWW-Authenticate'].split('qop="')[1].split('"')[0]
    nc = "00000001"
    cnonce = "f74b7289ebe104ac"
    # A1=md5(username:realm:password)
    A1 = md5(f"{user}:{realm}:{password}".encode()).hexdigest()
    # A2=md5(method:uri)
    A2 = md5(f"{method}:{uri}".encode()).hexdigest()
    # A3=nonce:nc:cnonce:qop
    if qop == "Undefined":
        # Digest=MD5(MD5(A1):<nonce>:MD5(A2))
        A3 = f"{nonce}"
    else:
        # Digest=MD5(MD5(A1):<nonce>:<nc>:<cnonce>:<qop>:MD5(A2))
        A3 = f"{nonce}:{nc}:{cnonce}:{qop}"
    response = md5(f"{A1}:{A3}:{A2}".encode()).hexdigest()
    data = f'Digest username="{user}", realm="{realm}", nonce="{nonce}", uri="{uri}", response="{response}", qop="{qop}", nc={nc}, cnonce="{cnonce}",Basic realm="{Basic_realm}"'
    hearders = {"Authorization": data}
    return hearders


def set_now_to_device_time(ip, user, password):
    # Authorization: Digest
    uri = "/ISAPI/System/time/localTime"
    hearders = digest_auth(ip, user, password, uri, method="PUT")
    data = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime())
    resp = requests.put(
        f"http://{ip}{uri}", headers=hearders, data=data, auth=(user, password))
    statusString = parse_xml(
        resp.text, "{http://www.hikvision.com/ver20/XMLSchema}statusString")
    print(statusString)
    return statusString


def get_the_OSD(ip, user, password):
    # Authorization: Digest
    uri = "/ISAPI/System/Video/inputs/channels/1"
    hearders = digest_auth(ip, user, password, uri, method="GET")
    resp = requests.get(f"http://{ip}{uri}",
                        headers=hearders, auth=(user, password))
    name = parse_xml(
        resp.text, "{http://www.hikvision.com/ver20/XMLSchema}name")
    print(name)
    return name


#     解析xml
def parse_xml(xml, tag):
    root = ET.fromstring(xml)
    for child in root:
        # print(child.tag, child.text)
        if child.tag == tag:
            return child.text


def set_the_OSD_parameters(ip, user, password, osd):
    # Authorization: Digest
    uri = "/ISAPI/System/Video/inputs/channels/1"
    hearders = digest_auth(ip, user, password, uri, method="PUT")
    data = f'<?xml version="1.0" encoding="UTF-8"?>' \
           '<VideoInputChannel version="2.0" xmlns="http://www.hikvision.com/ver20/XMLSchema">' \
           '<id>1</id>' \
           '<inputPort>1</inputPort>' \
           f'<name>{osd}</name>' \
           '<videoFormat>PAL</videoFormat>' \
           '</VideoInputChannel>'
    resp = requests.put(f"http://{ip}{uri}", headers=hearders,
                        data=data.encode("utf-8"), auth=(user, password))
    statusString = parse_xml(
        resp.text, "{http://www.hikvision.com/ver20/XMLSchema}statusString")
    print(statusString)
    return statusString


def get_network_parameters(ip, user, password):
    # Authorization: Digest
    uri = "/ISAPI/System/Network/interfaces"
    hearders = digest_auth(ip, user, password, uri, method="GET")
    resp = requests.get(f"http://{ip}{uri}",
                        headers=hearders, auth=(user, password))
    root = ET.fromstring(resp.text)
    ip = ""
    mask = ""
    gateway = ""
    dns1 = ""
    dns2 = ""
    dhcp = ""
    for child in root:
        if child.tag == "{http://www.hikvision.com/ver20/XMLSchema}NetworkInterface":
            for child1 in child:
                if child1.tag == "{http://www.hikvision.com/ver20/XMLSchema}IPAddress":
                    for child2 in child1:
                        # print(child2.tag, child2.text)
                        if child2.tag == "{http://www.hikvision.com/ver20/XMLSchema}addressingType":
                            # print(child2.text)
                            dhcp = child2.text
                            continue
                        elif child2.tag == "{http://www.hikvision.com/ver20/XMLSchema}ipAddress":
                            # print(child2.text)
                            ip = child2.text
                            continue
                        elif child2.tag == "{http://www.hikvision.com/ver20/XMLSchema}subnetMask":
                            # print(child2.text)
                            mask = child2.text
                            continue
                        # 网关
                        elif child2.tag == "{http://www.hikvision.com/ver20/XMLSchema}DefaultGateway":
                            for child3 in child2:
                                if child3.tag == "{http://www.hikvision.com/ver20/XMLSchema}ipAddress":
                                    # print(child3.text)
                                    gateway = child3.text
                                    continue
                            continue
                        # DNS
                        elif child2.tag == "{http://www.hikvision.com/ver20/XMLSchema}PrimaryDNS":
                            for child3 in child2:
                                if child3.tag == "{http://www.hikvision.com/ver20/XMLSchema}ipAddress":
                                    # print(child3.text)
                                    dns1 = child3.text
                                    continue
                            continue
                        # DNS
                        elif child2.tag == "{http://www.hikvision.com/ver20/XMLSchema}SecondaryDNS":
                            for child3 in child2:
                                if child3.tag == "{http://www.hikvision.com/ver20/XMLSchema}ipAddress":
                                    # print(child3.text)
                                    dns2 = child3.text
                                    continue
                            continue
    return dhcp, ip, mask, gateway, dns1, dns2


def set_network_parameters(ip, user, password, dhcp, ip2, mask, gateway, dns1, dns2):
    # Authorization: Digest
    uri = "/ISAPI/System/Network/interfaces/1/ipAddress"
    hearders = digest_auth(ip, user, password, uri, method="PUT")
    if dhcp:
        dhcp_value = "dynamic"
    else:
        dhcp_value = "static"
    data = '<?xml version="1.0" encoding="UTF-8"?>' \
           '<NetworkInterface><id>1</id>' \
           '<IPAddress><ipVersion>dual</ipVersion>' \
           f'<addressingType>{dhcp_value}</addressingType>' \
           f'<ipAddress>{ip2}</ipAddress>' \
           f'<subnetMask>{mask}</subnetMask>' \
           '<ipV6AddressingType>ra</ipV6AddressingType>' \
           '<DefaultGateway>' \
           f'<ipAddress>{gateway}</ipAddress>' \
           '</DefaultGateway>' \
           '<PrimaryDNS>' \
           f'<ipAddress>{dns1}</ipAddress>' \
           '</PrimaryDNS>' \
           '<SecondaryDNS>' \
           f'<ipAddress>{dns2}</ipAddress>' \
           '</SecondaryDNS>' \
           '</IPAddress>' \
           '</NetworkInterface>'
    # print(data)
    resp = requests.put(f"http://{ip}{uri}", headers=hearders,
                        data=data.encode("utf-8"), auth=(user, password))
    # print(resp.text)
    statusString = parse_xml(
        resp.text, "{http://www.hikvision.com/ver20/XMLSchema}statusString")
    print(statusString)
    return statusString


def reboot_device(ip, user, password):
    # Authorization: Digest
    uri = "/ISAPI/System/reboot"
    hearders = digest_auth(ip, user, password, uri, method="PUT")
    resp = requests.put(f"http://{ip}{uri}",
                        headers=hearders, auth=(user, password))
    # print(resp.text)
    statusString = parse_xml(
        resp.text, "{http://www.hikvision.com/ver20/XMLSchema}statusString")
    print(statusString)
    return statusString


if __name__ == "__main__":
    ip = "192.168.10.148"
    user = "admin"
    password = "abc12345"
    # digest_auth_picture(ip, user, password, "test_digest.jpg")
    # basic_auth_picture(ip, user, password, "test_basic.jpg")
    # set_now_to_device_time(ip, user, password)
    # set_the_OSD_parameters(ip, user, password, "测试通道2")
    # get_the_OSD(ip, user, password)
    # print(get_network_parameters(ip, user, password))
    set_network_parameters(ip, user, password, False, "192.168.10.148", "255.255.252.0", "192.168.10.1", "223.5.5.5",
                           "114.114.114.114")
    # reboot_device(ip, user, password)
